package com.yoyo.itravel.service.impl;

import com.yoyo.itravel.bean.*;
import com.yoyo.itravel.constants.MsgConstant;
import com.yoyo.itravel.dao.*;
import com.yoyo.itravel.exceptions.SightException;
import com.yoyo.itravel.exceptions.TicketTypeException;
import com.yoyo.itravel.service.ISightService;
import com.yoyo.itravel.service.ITicketTypeService;
import com.yoyo.itravel.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.List;

/**
 * @Description 景点操作服务层接口实现类
 * @Author HZX
 * @Version 1.0
 * @Date 2020/6/22 20:10
 */
@Service
public class SightServiceImpl implements ISightService {

    @Autowired
    private ISightDao sightDao;
    @Autowired
    private ITicketTypeDao ticketTypeDao;
    @Autowired
    private ITicketTypeDetailDao ticketTypeDetailDao;
    @Autowired
    private ITicketTypeService ticketTypeService;
    @Autowired
    private ISightImgDao sightImgDao;
    @Autowired
    private ICountryDao countryDao;
    @Autowired
    private IProvinceDao provinceDao;
    @Autowired
    private ICityDao cityDao;
    @Autowired
    private ISightThemeDao sightThemeDao;
    @Autowired
    // 景点-主题中间表Dao接口对象
    private ISightThemeSightDao sightThemeSightDao;
    @Autowired
    // 景点门票库存操作持久层接口对象
    private ISightTicketStockDao sightTicketStockDao;
    @Autowired
    // 景点所属公司操作持久层接口对象
    private ISightCompanyDao sightCompanyDao;

    /**
     * @Description 新增景点
     *
     * @param sight
     * @param imageUrls 景点详情图片url
     * @param themeIds 景点主题id
     * @return boolean
     */
    @Override
    public boolean addSight(Sight sight, List<String> imageUrls, List<String> themeIds) throws SightException {
        // 判断sight对象是否为null
        if (sight == null) {
            throw new SightException("传入的景点对象为null...");
        }

        try {
            /** 2.补充信息 **/
            String sightId = StringUtils.getRandomUUID();
            sight.setSightId(sightId);
            sight.setSellCount(0);
            sight.setCollectCount(0);

            /** 3.新增景点 **/
            // 插入景点，添加景点详情图片
            if (sightDao.insert(sight) == 1 && imageUrls != null && imageUrls.size() > 0) {
                for (String imgUrl : imageUrls) {
                    System.out.println(imgUrl);
                    // 构建景点图片对象
                    SightImg sightImg = new SightImg(StringUtils.getRandomUUID(), imgUrl, sightId);
                    sightImgDao.insert(sightImg);
                }
            }
            if (themeIds != null && themeIds.size() > 0) {
                for (String themeId : themeIds) {
                    // 为景点添加主题
                    sightThemeSightDao.insert(sightId, themeId);
                }
            }
            // 返回
            return true;
        } catch (SQLException e) {
            e.printStackTrace();
            throw new SightException(MsgConstant.INTERNAL_ERR);
        }
    }

    /**
     * @Description 根据条件查询景点
     *
     * @Param themeId
     * @Param provinceId
     * @Param cityId
     * @Return java.util.List<com.yoyo.itravel.bean.Sight>
     */
    @Override
    public List<Sight> findSightByCondition(String themeId, String provinceId, String cityId) throws SightException {
        try {
            return sightDao.selectByCondition(themeId, provinceId, cityId, "");
        } catch (SQLException e) {
            e.printStackTrace();
            throw new SightException(MsgConstant.INTERNAL_ERR);
        }
    }

    /**
     * @Description 根据条件分页查询景点信息
     *
     * @Param themeId
     * @Param provinceId
     * @Param cityId
     * @Param currentPage
     * @Param pageSize
     * @Param search
     * @Param lowPrice
     * @Param heightPrice
     * @Return com.yoyo.itravel.bean.PageBean<com.yoyo.itravel.bean.Sight>
     */
    @Override
    public PageBean<Sight> queryCurrentPageByCondition(String themeId, String provinceId, String cityId, int currentPage, int pageSize, String search, String lowPrice, String heightPrice) throws SightException {
        //封装PageBean
        PageBean<Sight> pb = new PageBean<Sight>();
        //设置当前页码
        pb.setCurrentPage(currentPage);
        //设置每页显示条数
        pb.setPageSize(pageSize);

        //设置当前页显示的数据集合
        int start = (currentPage - 1) * pageSize; // 开始的记录数

        // 根据选择的条件获得的景点集合
        List<Sight> sights = null;
        // 定义一个变量，表示总条数
        int totalCount = 0;

        try {
            // 查询的数据的总条数
            totalCount = sightDao.selectCountByCondition(themeId, provinceId, cityId, search);

            // 根据选择的条件来查询景点，获得景点集合
            sights = sightDao.selectPageByCondition(themeId, provinceId, cityId, start, pageSize, search);

            if (sights != null) {
                Iterator<Sight> iterator = sights.iterator();
                // 遍历所查到的景点
                while (iterator.hasNext()) {

                    Sight sight = iterator.next();

                    // 根据景点id查找的景点门票具体类型的最低价
                    BigDecimal lowestPrice = ticketTypeService.findLowestPriceBySightId(sight.getSightId());

                    if (lowestPrice == null) {
                        // 如果该景点查出来的最低价为null，即该景点未售票
                        // 因为 Null key for a Map not allowed in JSON，会报异常
                        // 所以这里必须要将Sight作为key来传输
                        lowestPrice = new BigDecimal("0");
                    }
                    // 最低价判断
                    if (!"".equals(lowPrice) && lowPrice != null) {
                        BigDecimal low_price = new BigDecimal(lowPrice);
                        if (lowestPrice.subtract(low_price).intValue() < 0) {
                            // 移除该景点
                            iterator.remove();
                            // 数据总数减一
                            totalCount--;
                        }
                    }
                    // 最高价判断
                    if (!"".equals(heightPrice) && heightPrice != null) {
                        BigDecimal height_price = new BigDecimal(heightPrice);
                        if (lowestPrice.subtract(height_price).intValue() > 0) {
                            // 移除该景点
                            iterator.remove();
                            // 数据总数减一
                            totalCount--;
                        }
                    }

                    // 将最低价和景点对象放入集合
                    sight.setLowestPrice(lowestPrice);
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
            throw new SightException(MsgConstant.INTERNAL_ERR);
        } catch (TicketTypeException e) {
            e.printStackTrace();
            throw new SightException(MsgConstant.INTERNAL_ERR);
        }

        // 设置总条数
        pb.setTotalCount(totalCount);

        pb.setList(sights);

        //设置总页数 = 总记录数/每页显示条数
        int totalPage = totalCount % pageSize == 0 ? totalCount / pageSize : (totalCount / pageSize) + 1;
        pb.setTotalPage(totalPage);

        return pb;
    }

    /**
     * @Description 查找销量最高的景点
     *
     * @Param size
     * @Return java.util.List<com.yoyo.itravel.bean.Sight>
     */
    @Override
    public List<Sight> findSellestSight(Integer size) throws SightException {
        try {
            // 根据选择的条件来查询景点，获得景点集合
            List<Sight> sights = sightDao.selectSellestSight(size);

            if (sights != null) {
                // 遍历所查到的景点
                for (Sight sight : sights) {
                    // 根据景点id查找的景点门票具体类型的最低价
                    BigDecimal lowestPrice = ticketTypeService.findLowestPriceBySightId(sight.getSightId());

                    if (lowestPrice == null) {
                        // 如果该景点查出来的最低价为null，即该景点未售票
                        // 因为 Null key for a Map not allowed in JSON，会报异常
                        // 所以这里必须要将Sight作为key来传输
                        lowestPrice = new BigDecimal("0");
                    }

                    // 将最低价和景点对象放入map集合--注意：不能直接放入map，而应该先使用LinkHashMap，以保证他的添加顺序
                    sight.setLowestPrice(lowestPrice);
                }
            }

            return sights;
        } catch (SQLException e) {
            e.printStackTrace();
            throw new SightException(MsgConstant.INTERNAL_ERR);
        } catch (TicketTypeException e) {
            e.printStackTrace();
            throw new SightException(MsgConstant.INTERNAL_ERR);
        }

    }

    /**
     * @Description 分页查询所有景点
     *
     * @Param page
     * @Return cn.hut.travel.bean.PageBean<cn.hut.travel.bean.Sight>
     */
    @Override
    public List<Sight> findAllByPage(PageBean page) throws SightException {

        if (page == null) {
            return null;
        }

        // 根据选择的条件获得的景点集合
        List<Sight> sights = null;

        try {
            // 获得所有景点
            sights = sightDao.selectAllByPage(page.getStartPage(), page.getPageSize());

            if (sights != null && sights.size() > 0) {
                for (Sight sight : sights) {
                    // 获得景点所属公司对象
                    SightCompany sightCompany = sightCompanyDao.selectById(sight.getSightCompanyId());
                    // 查找该景点所属主题
                    List<SightTheme> sightThemes = sightThemeDao.selectAllBySightId(sight.getSightId());
                    sight.setSightThemes(sightThemes);
                    // 通过景点所属国家id获得景点国家对象
                    Country country = sight.getCountryId() == null ? null : countryDao.selectByCountryId(sight.getCountryId());
                    // 通过景点所属省份id获得景点国家对象
                    Province province = provinceDao.selectByProvinceId(sight.getProvinceId());
                    // 通过景点所属城市id获得景点国家对象
                    City city = cityDao.selectByCityId(sight.getCityId());

                    // 添加景点所属国家对象
                    sight.setCountry(country);
                    // 添加景点所属省份对象
                    sight.setProvince(province);
                    // 添加景点所属城市对象
                    sight.setCity(city);
                    // 添加景点公司对象
                    sight.setSightCompany(sightCompany);
                }
            }

            // TODO 排除当前登录的管理员
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return sights;
    }

    /**
     * @Description 查找用户收藏量最高的景点--注意：如果使用了Map集合，会使得逆序排序的数据，变为无序，这里要使用Map的子类LinkHashMap
     *
     * @Param size
     * @Return java.util.List<com.yoyo.itravel.bean.Sight>
     */
    @Override
    public List<Sight> findCollectestSight(Integer size) throws SightException {
        // 构建一个LinkedHashMap集合
        List<Sight> sights = null;

        try {
            // 根据选择的条件来查询景点，获得景点集合
            sights = sightDao.selectCollectestSight(size);

            if (sights != null) {
                // 遍历所查到的景点
                for (Sight sight : sights) {
                    // 根据景点id查找的景点门票具体类型的最低价
                    BigDecimal lowestPrice = ticketTypeService.findLowestPriceBySightId(sight.getSightId());

                    if (lowestPrice == null) {
                        // 如果该景点查出来的最低价为null，即该景点未售票
                        // 因为 Null key for a Map not allowed in JSON，会报异常
                        // 所以这里必须要将Sight作为key来传输
                        lowestPrice = new BigDecimal("0");
                    }

                    // 将最低价和景点对象放入map集合--注意：不能直接放入map，而应该先使用LinkHashMap，以保证他的添加顺序
                    sight.setLowestPrice(lowestPrice);
                }
            }
            return sights;
        } catch (SQLException e) {
            e.printStackTrace();
            throw new SightException(MsgConstant.INTERNAL_ERR);
        } catch (TicketTypeException e) {
            e.printStackTrace();
            throw new SightException(MsgConstant.INTERNAL_ERR);
        }
    }

    /**
     * @Description 查询景点数据的总条数
     * @Param
     * @Return java.lang.Integer
     */
    @Override
    public Integer findTotalCount() throws SightException {
        try {
            return sightDao.selectTotalCount();
        } catch (SQLException e) {
            e.printStackTrace();
            throw new SightException("查询景点数据的总条数失败！");
        }
    }

    /**
     * @Description 通过景点id修改景点的在售状态
     *
     * @Param sightId
     * @Param newStatus
     * @Return boolean
     */
    @Override
    public boolean updateOnSellStatusById(String sightId, Integer newStatus) throws SightException {
        // 判断id是否为空
        if (StringUtils.isEmpty(sightId)) {
            throw new SightException("景点ID为空！");
        }
        // 判断新的在售状态是否合法
        if (newStatus != 0 && newStatus != 1) {
            throw new SightException("新的在售状态不合法！");
        }
        try {
            return sightDao.updateOnSellStatusById(sightId, newStatus) == 1;
        } catch (SQLException e) {
            e.printStackTrace();
            throw new SightException("通过景点id修改景点的在售状态失败！");
        }
    }

    /**
     * @Description 通过景点id和主题id删除景点主题
     * @Param sightId
     * @Param themeId
     * @Return boolean
     */
    @Override
    public boolean deleteSightTheme(String sightId, String themeId) throws SightException {
        // 非空判断
        if (StringUtils.isEmpty(sightId, themeId)) {
            throw new SightException("景点id或主题id为空！");
        }

        try {
            return sightThemeSightDao.deleteBySightIdAndThemeId(sightId, themeId) == 1;
        } catch (SQLException e) {
            e.printStackTrace();
            throw new SightException("通过景点id和主题id删除景点主题失败！");
        }
    }

    /**
     * @Description 通过景点id删除景点
     * @Param sightId
     * @Return boolean
     */
    @Override
    public boolean deleteSight(String sightId) throws SightException {
        // 非空判断
        if (StringUtils.isEmpty(sightId)) {
            throw new SightException("景点id为空！");
        }

        try {
            return sightDao.deleteById(sightId) == 1;
        } catch (SQLException e) {
            e.printStackTrace();
            throw new SightException("通过景点id删除景点失败！");
        }
    }

    /**
     * @Description 通过id批量删除景点
     * @Param ids
     * @Return boolean
     */
    @Override
    public boolean deleteBatch(String[] ids) throws SightException {
        // 判断ids是否为空
        if (ids == null || ids.length < 1) {
            throw new SightException("ID数组为空！");
        }
        try {
            // 批量删除景点
            sightDao.deleteBatch(ids);
            return true;
        } catch (SQLException e) {
            e.printStackTrace();
            throw new SightException("通过id批量删除景点失败！");
        }
    }

    /**
     * @Description 根据条件获得查询的景点数据条数
     *
     * @Param themeId
     * @Param provinceId
     * @Param cityId
     * @Param search
     * @Return int
     */
    @Override
    public int selectCountByCondition(String themeId, String provinceId, String cityId, String search) throws SightException {
        try {
            return sightDao.selectCountByCondition(themeId, provinceId, cityId, search);
        } catch (SQLException e) {
            e.printStackTrace();
            throw new SightException(MsgConstant.INTERNAL_ERR);
        }
    }

    /**
     * @Description 通过景点id查询景点
     *
     * @Param sightId
     * @Return com.yoyo.itravel.bean.Sight
     */
    @Override
    public Sight findSightBySightId(String sightId) throws SightException {
        try {
            // 通过景点id获得景点对象
            Sight sight = sightDao.selectBySightId(sightId);

            // 通过景点id获得景点图片集合
            List<SightImg> sightImgs = sightImgDao.selectBySightId(sightId);
            // 通过景点id获得景点门票类型
            List<TicketType> ticketTypes = ticketTypeDao.selectBySightId(sightId);
            // 通过ticketTypes集合获得迭代器
            Iterator<TicketType> iterator = ticketTypes.iterator();

            // 遍历迭代器集合，补充ticketTypeDetails信息
            while (iterator.hasNext()) {
                TicketType ticketType = iterator.next();
                List<TicketTypeDetail> ticketTypeDetails = ticketTypeDetailDao.selectByTicketTypeId(ticketType.getTicketTypeId());
                // 判断ticketTypeDetails是否为null
                if (ticketTypeDetails == null || ticketTypeDetails.size() == 0) {
                    // 则移除当前的门票类型
                    iterator.remove();
                    continue;
                }
                // 遍历ticketTypeDetails集合
                for (TicketTypeDetail ticketTypeDetail : ticketTypeDetails) {
                    // 通过景点门票详细类型id获得景点门票库存集合
                    List<SightTicketStock> sightTicketStocks = sightTicketStockDao.selectByCondition(new SightTicketStock(ticketTypeDetail.getDetailTypeId()));
                    // 将景点门票库存集合设置到ticketTypeDetail对象中
                    ticketTypeDetail.setSightTicketStocks(sightTicketStocks);
                }
                // 将ticketTypeDetails集合设置到ticketType中
                ticketType.setTicketTypeDetails(ticketTypeDetails);
            }
            // 通过景点所属国家id获得景点国家对象
            Country country = countryDao.selectByCountryId(sight.getCountryId());
            // 通过景点所属省份id获得景点国家对象
            Province province = provinceDao.selectByProvinceId(sight.getProvinceId());
            // 通过景点所属城市id获得景点国家对象
            City city = cityDao.selectByCityId(sight.getCityId());
            // 通过景点所属公司id获得所属公司对象
            SightCompany sightCompany = sightCompanyDao.selectById(sight.getSightCompanyId());

            /** 补充景点对象中的值 **/
            // 将景点图片集合添加到sight对象
            sight.setSightImgList(sightImgs);
            // 将景点门票类型集合添加到sight对象
            sight.setTicketTypeList(ticketTypes);
            // 添加景点所属国家对象
            sight.setCountry(country);
            // 添加景点所属省份对象
            sight.setProvince(province);
            // 添加景点所属城市对象
            sight.setCity(city);
            // 添加景点所属公司对象
            sight.setSightCompany(sightCompany);

            System.out.println(sightCompany);

            return sight;
        } catch (SQLException e) {
            e.printStackTrace();
            throw new SightException(MsgConstant.INTERNAL_ERR);
        }
    }

    /**
     * @param sightId
     * @param count
     * @return boolean
     * @Description 通过景点id更新景点门票销量
     */
    @Override
    public boolean updateSellCount(String sightId, Integer count) throws SightException {
        if (StringUtils.isEmpty(sightId)) {
            throw new SightException("景点id为空！");
        }
        try {
            return sightDao.updateSellCount(sightId, count) == 1;
        } catch (SQLException e) {
            e.printStackTrace();
            throw new SightException("通过景点id更新景点门票销量失败！");
        }
    }

    /**
     * @param sightId
     * @param isAdd
     * @return boolean
     * @Description 通过景点id更新景点被收藏的次数
     */
    @Override
    public boolean updateCollectCount(String sightId, boolean isAdd) throws SightException {
        if (StringUtils.isEmpty(sightId)) {
            throw new SightException("景点id为空！");
        }
        try {
            return sightDao.updateCollectCount(sightId, isAdd) == 1;
        } catch (SQLException e) {
            e.printStackTrace();
            throw new SightException("通过景点id更新景点被收藏的次数失败！");
        }
    }

}
